using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using System;
namespace ICSharpCode.SharpZipLib.Zip.Compression
{
	internal class InflaterDynHeader
	{
		private const int LNUM = 0;
		private const int DNUM = 1;
		private const int BLNUM = 2;
		private const int BLLENS = 3;
		private const int LENS = 4;
		private const int REPS = 5;
		private static readonly int[] repMin = new int[]
		{
			3,
			3,
			11
		};
		private static readonly int[] repBits = new int[]
		{
			2,
			3,
			7
		};
		private static readonly int[] BL_ORDER = new int[]
		{
			16,
			17,
			18,
			0,
			8,
			7,
			9,
			6,
			10,
			5,
			11,
			4,
			12,
			3,
			13,
			2,
			14,
			1,
			15
		};
		private byte[] blLens;
		private byte[] litdistLens;
		private InflaterHuffmanTree blTree;
		private int mode;
		private int lnum;
		private int dnum;
		private int blnum;
		private int int_0;
		private int repSymbol;
		private byte lastLen;
		private int int_1;
		public bool Decode(StreamManipulator input)
		{
			while (true)
			{
				switch (this.mode)
				{
				case 0:
					this.lnum = input.PeekBits(5);
					if (this.lnum >= 0)
					{
						this.lnum += 257;
						input.DropBits(5);
						this.mode = 1;
						goto IL_20B;
					}
					goto IL_2D6;
				case 1:
					goto IL_20B;
				case 2:
					goto IL_1B8;
				case 3:
					goto IL_17D;
				case 4:
					break;
				case 5:
					goto IL_06;
				default:
					continue;
				}
				IL_E3:
				int symbol;
				while (((symbol = this.blTree.GetSymbol(input)) & -16) == 0)
				{
					this.litdistLens[this.int_1++] = (this.lastLen = (byte)symbol);
					if (this.int_1 == this.int_0)
					{
						goto IL_2F0;
					}
				}
				if (symbol >= 0)
				{
					if (symbol >= 17)
					{
						this.lastLen = 0;
					}
					else
					{
						if (this.int_1 == 0)
						{
							goto IL_2EA;
						}
					}
					this.repSymbol = symbol - 16;
					this.mode = 5;
					goto IL_06;
				}
				goto IL_2E6;
				IL_17D:
				while (this.int_1 < this.blnum)
				{
					int num = input.PeekBits(3);
					if (num < 0)
					{
						goto IL_2E2;
					}
					input.DropBits(3);
					this.blLens[InflaterDynHeader.BL_ORDER[this.int_1]] = (byte)num;
					this.int_1++;
				}
				this.blTree = new InflaterHuffmanTree(this.blLens);
				this.blLens = null;
				this.int_1 = 0;
				this.mode = 4;
				goto IL_E3;
				IL_06:
				int bitCount = InflaterDynHeader.repBits[this.repSymbol];
				int num2 = input.PeekBits(bitCount);
				if (num2 < 0)
				{
					goto IL_2F4;
				}
				input.DropBits(bitCount);
				num2 += InflaterDynHeader.repMin[this.repSymbol];
				if (this.int_1 + num2 > this.int_0)
				{
					break;
				}
				while (num2-- > 0)
				{
					this.litdistLens[this.int_1++] = this.lastLen;
				}
				if (this.int_1 != this.int_0)
				{
					this.mode = 4;
					continue;
				}
				goto IL_2FE;
				IL_1B8:
				this.blnum = input.PeekBits(4);
				if (this.blnum >= 0)
				{
					this.blnum += 4;
					input.DropBits(4);
					this.blLens = new byte[19];
					this.int_1 = 0;
					this.mode = 3;
					goto IL_17D;
				}
				goto IL_2DE;
				IL_20B:
				this.dnum = input.PeekBits(5);
				if (this.dnum >= 0)
				{
					this.dnum++;
					input.DropBits(5);
					this.int_0 = this.lnum + this.dnum;
					this.litdistLens = new byte[this.int_0];
					this.mode = 2;
					goto IL_1B8;
				}
				goto IL_2DA;
			}
			throw new SharpZipBaseException();
			IL_2D6:
			bool result = false;
			return result;
			IL_2DA:
			result = false;
			return result;
			IL_2DE:
			result = false;
			return result;
			IL_2E2:
			result = false;
			return result;
			IL_2E6:
			result = false;
			return result;
			IL_2EA:
			throw new SharpZipBaseException();
			IL_2F0:
			result = true;
			return result;
			IL_2F4:
			result = false;
			return result;
			IL_2FE:
			result = true;
			return result;
		}
		public InflaterHuffmanTree BuildLitLenTree()
		{
			byte[] array = new byte[this.lnum];
			Array.Copy(this.litdistLens, 0, array, 0, this.lnum);
			return new InflaterHuffmanTree(array);
		}
		public InflaterHuffmanTree BuildDistTree()
		{
			byte[] array = new byte[this.dnum];
			Array.Copy(this.litdistLens, this.lnum, array, 0, this.dnum);
			return new InflaterHuffmanTree(array);
		}
	}
}
